package utils

import (
	"fmt"
	"github.com/xuri/excelize/v2"
	"reflect"
	"strconv"
)

func GetExcelName(filedName string, T any) string {
	t := reflect.TypeOf(T)
	field, _ := t.FieldByName(filedName)
	ret := field.Tag.Get("excel")
	return ret

}

func GetExcelNameByStruct(a any) map[string]string {
	m := make(map[string]string)
	typ := reflect.TypeOf(a)
	val := reflect.ValueOf(a) //获取reflect.Type类型
	kd := val.Kind()          //获取到a对应的类别
	if kd != reflect.Struct {
		fmt.Println("expect struct")
		return m
	}
	//获取到该结构体有几个字段
	num := val.NumField()
	//fmt.Printf("该结构体有%d个字段\n", num) //4个

	//遍历结构体的所有字段
	for i := 0; i < num; i++ {
		//fmt.Printf("Field %v\n", typ.Field(i).Name)
		//获取到struct标签，需要通过reflect.Type来获取tag标签的值
		tagVal := typ.Field(i).Tag.Get("excel")
		//如果该字段有tag标签就显示，否则就不显示
		if tagVal != "" {
			//fmt.Printf("Field %v:tag=%v\n", typ.Field(i).Name, tagVal)
			m[typ.Field(i).Name] = tagVal
		}
	}

	return m

}

func GetExcelNameByStruct2(a any) map[string]string {
	m := make(map[string]string)
	typ := reflect.TypeOf(a)
	val := reflect.ValueOf(a) //获取reflect.Type类型
	kd := val.Kind()          //获取到a对应的类别
	if kd != reflect.Struct {
		fmt.Println("expect struct")
		return m
	}
	//获取到该结构体有几个字段
	num := val.NumField()
	//fmt.Printf("该结构体有%d个字段\n", num) //4个

	//遍历结构体的所有字段
	for i := 0; i < num; i++ {
		//fmt.Printf("Field %v\n", typ.Field(i).Name)
		//获取到struct标签，需要通过reflect.Type来获取tag标签的值
		tagVal := typ.Field(i).Tag.Get("excel")
		//如果该字段有tag标签就显示，否则就不显示
		if tagVal != "" {
			//fmt.Printf("Field %v:tag=%v\n", typ.Field(i).Name, tagVal)
			//m[typ.Field(i).Name] = tagVal
			m[tagVal] = typ.Field(i).Name
		}
	}

	return m

}

func CreateExcel[test any](fileName string, T []test) string {
	//长度暂时定为26，后面可以继续加
	var excelIndex = []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
	m := GetExcelNameByStruct(T[0])
	var i = 0
	f := excelize.NewFile()
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()
	// 遍历 Map
	for k, v := range m {
		//fmt.Printf("key=%s, value=%s\n", k, v)
		f.SetCellValue("Sheet1", excelIndex[i]+"1", v)
		m[k] = excelIndex[i]
		i++
	}

	var k = 2
	for _, value := range T {

		typ := reflect.TypeOf(value)
		val := reflect.ValueOf(value)
		num := val.NumField()
		for j := 0; j < num; j++ {

			name := typ.Field(j).Name
			valueExcel := val.Field(j)
			excelRow := m[name]
			s := fmt.Sprintf("%s%d", excelRow, k)
			f.SetCellValue("Sheet1", s, valueExcel)

		}
		k++

	}

	if err := f.SaveAs(fileName); err != nil {
		fmt.Println(err)
	}

	return "ok"

}

func ReadExcel[test any](fileName string, tmp test) (T []test) {
	//长度暂时定为26，后面可以继续加
	//var excelIndex = []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}

	f, err := excelize.OpenFile(fileName)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer func() {
		// 关闭工作簿
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	m := GetExcelNameByStruct2(tmp)
	cols, err := f.GetCols("Sheet1")
	if err != nil {
		fmt.Println(err)
		return
	}
	var testRet []test = make([]test, len(cols)-1)
	fmt.Print(len(cols)-1, "\t")
	for _, col := range cols {
		var ff = true

		var name = ""
		var i = 0
		for _, colCell := range col {
			fmt.Print(colCell, "\t")
			if ff {

				name = m[colCell]

				ff = false
				fmt.Print(name, "\t")
			} else {

				tmp := testRet[i]
				val := reflect.ValueOf(&tmp).Elem()
				typ := reflect.TypeOf(tmp)
				field, _ := typ.FieldByName(name)
				ret := field.Type.Name()
				switch ret {
				case "string":
					val.FieldByName(name).SetString(colCell)
				case "int":
					//num2, _ :=  strconv.Atoi(colCell)
					num2, _ := strconv.ParseInt(colCell, 10, 64)
					val.FieldByName(name).SetInt(num2)
				}

				testRet[i] = tmp
				i++
				if i == len(cols)-1 {
					break
				}
			}

		}
		fmt.Println()
	}

	return testRet

}

func CreateExcelByMap(fileName string, T []map[string]string, hearders map[string]string) string {

	var excelIndex = []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}

	var i = 0
	f := excelize.NewFile()
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	for k, v := range hearders {
		//fmt.Printf("key=%s, value=%s\n", k, v)
		f.SetCellValue("Sheet1", excelIndex[i]+"1", v)
		hearders[k] = excelIndex[i]
		i++

	}

	var j = 2
	for _, value := range T {

		for k, valueExcel := range value {
			excelRow := hearders[k]
			s := fmt.Sprintf("%s%d", excelRow, j)
			f.SetCellValue("Sheet1", s, valueExcel)
		}
		j++

	}

	if err := f.SaveAs(fileName); err != nil {
		fmt.Println(err)
	}

	return "ok"

}
